/*
 * Images - the "big-png" system. Notation within a png to denote subimages.
 *
 * Copyright 2007 James W. Hofmann
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

// this system needs to go at some point. It works for a few pieces of art,
// but a better art toolchain is possible.

package flash3f;

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.display.Loader;
import flash.net.URLRequest;

class Images
{
	public static var loader : flash.display.Loader;
	public static var rects : Array < Rectangle >;
	public static var data : IntHash<Bitmap>;		
	public static var tilecursor : Bitmap;
	
	public static function composenew(xsize : Int, ysize : Int, idlist : Array <Int>, poslist : Array <Point>) : BitmapData
	{
		var final : BitmapData = new BitmapData(xsize, ysize, true, 0x000000);	
		compose(final, idlist, poslist);
		return final;
	}
	
	public static function getbitmap(id : Int) : Bitmap
	{
		var newt : Bitmap = new Bitmap();
		var baset : Bitmap = data.get(id);
		newt.bitmapData = baset.bitmapData.clone();
		return newt;
	}

	public static function getdata(id : Int) : BitmapData
	{
		return data.get(id).bitmapData.clone();
	}
	
	public static function getref(id : Int) : Bitmap
	{
		return data.get(id);
	}
	
	public static function compose(final : BitmapData, idlist : Array <Int>, poslist : Array <Point>)
	{		
		
		for (n in 0 ... idlist.length)
		{
			var nextdata : BitmapData = data.get(idlist.pop()).bitmapData;
			var nextpoint : Point = poslist.pop();
			final.copyPixels(nextdata, nextdata.rect, nextpoint, nextdata, new Point(0,0), true);
		}
		
	}
	
	private static function testpix(pixelValue : Int ) : Int
	{	
					
		// vals are RGB
		
		if (pixelValue == 0xFF0000) return 1 // red
		else if (pixelValue == 0x00FF00) return 2 // green
		else if (pixelValue == 0x0000FF) return 3 // blue
		else return 0;
		
	}

	private static function testray(test : Point, len, xinc, yinc, endcol : Int, bitmap : Bitmap) : Point
	{
		var foundgreen : Bool = false;
	
		var working : Point = new Point(test.x, test.y);
		var keyval : Float;
		if (xinc>0) keyval = working.x
		else keyval = working.y;
		
		while (keyval<len) 
		{					
			working.x += xinc;
			working.y += yinc;

			if (xinc>0) keyval = working.x
			else keyval = working.y;	

			//DebugDisp.log(Std.string(working.x) + " / " + Std.string(working.y));
			
			if (foundgreen==false)
			{
				if (testpix(bitmap.bitmapData.getPixel(Std.int(working.x), Std.int(working.y))) == 2 )
					foundgreen = true;
			}
			else // blue or red depending on endcol
			{
				if (testpix(bitmap.bitmapData.getPixel(Std.int(working.x), Std.int(working.y))) == endcol )
					return working;
			}
			
		}
		return test;
	}
	
	public static function start(file : Dynamic)
	{

	
		rects = new Array();
	
		var basegfx : flash.display.Bitmap = new Bitmap();
		basegfx.opaqueBackground == 0xFF00FF;
		basegfx.bitmapData = file;
		
		//var myrect : Rectangle = new Rectangle(0,0,loader.content.width,loader.content.height);
		var myrect : Rectangle = new Rectangle(basegfx.width,basegfx.height);
		var mypoint : Point = new Point(0,0);
			
		// Create a bool array of searched/unsearched pixels
		// loop through the pixels until an unsearched one is found
		
		// unsearched pixels do these tests: 
		// 1. If the pixel is red, begin raycasting to look for a rectangle shape.
		// 2. Rays are casted right and down, looking for first a green and then a blue pixel.
		// 3. At blue pixels, more rays are casted to look for a red pixel, the other corner.
		// if this is found, make the rectangle, mark pixels of rect as searched.
		
		var pixsearch : Array < Array <Bool> >;
		var pixwidth : Array <Bool>;
		
		pixwidth = new Array();
		pixsearch = new Array();
		
		for (x in 0 ... Std.int(basegfx.width))
		{
			pixwidth.insert(0,false);
		}
		
		for (y in 0 ... Std.int(basegfx.height))
		{
			pixsearch.insert(0,pixwidth.copy());
		}
						
		var cont : Bool = true;
		var linehasrect : Bool = false;
		var curpx : Int = 0;
		var curpy : Int = 0;
		var count : Int = 0;
		
		while (cont==true) {			
			
			if (pixsearch[curpy][curpx]==false) {
				pixsearch[curpy][curpx]=true;
				
				// if pix is red
				if (testpix(basegfx.bitmapData.getPixel(curpx, curpy)) == 1)
				{				
					var startpoint : Point = new Point(curpx, curpy);
					
					// test for green and then blue
					
					var downray : Point = testray(startpoint, pixsearch.length, 
												    0, 1, 3, basegfx);
					var rightray : Point = testray(startpoint, pixsearch[0].length, 
												    1, 0, 3, basegfx);
				
					if (downray.y != startpoint.y && rightray.x != startpoint.x)
						{
								
							// test for green and then red
				
							var downray2 : Point = testray(rightray, pixsearch.length, 
															0, 1, 1, basegfx);
							var rightray2 : Point = testray(downray, pixsearch[0].length, 
															1, 0, 1, basegfx);						
						
							if (downray2.x == rightray2.x && downray2.y == rightray2.y) 
							{
								rects.insert(0, new Rectangle(startpoint.x+1, startpoint.y+1,
															  (downray2.x-startpoint.x)-1, 
															  (downray2.y-startpoint.y)-1));
								
								
								count+=1;								
								curpx += 2;	// we can skip at least two pixels
							}						
						}
				}				
			}

			curpx += 1;
			
			if (curpx>=pixsearch[0].length)
			{		
				curpx = 0;
				curpy += 1;
			}
			
			if (curpy>=pixsearch.length)
			{
				curpx = 0;
				curpy = 0;
				cont = false;
			}
			
		}		
		
		data = new IntHash();
		var defpoint : Point = new Point(0,0);
		for (r in rects)
		{
			// the id of each image is taken from the pixel directly right of the upper left corner of
			// the bounding box pixels.
			// This means that 1x1 images will always have an ID of 0x00FF00;
			// however, I don't anticipate market demand for 1x1 images.
			var idnum : Int = basegfx.bitmapData.getPixel(Std.int(r.x),Std.int(r.y-1));
			var newimg : Bitmap = new Bitmap();
			newimg.bitmapData = new BitmapData(Std.int(r.width), Std.int(r.height), true, 0x000000);			
			newimg.bitmapData.copyPixels(basegfx.bitmapData, r, defpoint);
			data.set(idnum, newimg);
		}
				
		basegfx.bitmapData.dispose();
		basegfx = null;

		Main.loop();
		
	}
		
}
